package cn.cas.mango.util.dbscan;

import co.elastic.clients.elasticsearch._types.SortOrder;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

/**
 * 簇中的元素类
 */
public class Data implements Comparable<Data> {
    private String id;
    private final Set<String> keywords;
    private SortOrder sortOrder;
    private String sortField;
    private Date newsPublicDate;
    private Double newsScore;

    private boolean visited;

    private boolean added;

    public String getId() {
        return id;
    }

    public boolean isAdded() {
        return added;
    }

    public void setAdded() {
        this.added = true;
    }
    public boolean isVisited() {
        return visited;
    }

    public void setVisited() {
        this.visited = true;
    }

    public Data() {
        keywords = new HashSet<>();
        visited = false;
    }

    public Data(String id) {
        this();
        this.id = id;
    }

    public Data(String id, Set<String> keywords,
                String newsPublicDate, Double newsScore,
                SortOrder sortOrder, String sortField) {
        this(id);
        this.keywords.addAll(keywords);
        try {
            this.newsPublicDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(newsPublicDate);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        this.newsScore = newsScore;
        this.sortOrder = sortOrder;
        this.sortField = sortField;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Data)) return false;
        Data data = (Data) o;
        return Objects.equals(keywords, data.keywords);
    }

    @Override
    public int hashCode() {
        return Objects.hash(keywords);
    }

    /**
     * 计算相似度
     * @param data2，要与当前类
     * @return
     */
    public double calSim(Data data2) {
        Set<String> values2 = data2.keywords;
        double inter = calInter(values2).size();
        double union = calUnion(values2).size();
        double sim = (inter + 0.01) / (union + 0.01);
        if (keywords.size() == 0 || data2.keywords.size() == 0) {
          sim = 0;
        }
        return sim;
    }

    private Set<String> calUnion(Set<String> value2) {
        Set<String> strings = new HashSet<>(keywords);
        strings.addAll(value2);
//        strings.addAll(keywords);
        return strings;
    }

    private Set<String> calInter(Set<String> values2) {
        Set<String> strings = new HashSet<>(keywords);
        strings.retainAll(values2);
        return strings;
    }

    @Override
    public int compareTo(Data d2) {
        Date date1 = newsPublicDate;
        Date date2 = d2.newsPublicDate;
        int scoreRes = newsScore.compareTo(d2.newsScore);
        int dateRes = date1.compareTo(date2);
        if (sortField.equals("_score")) {
          if (scoreRes == 0) {
            return -dateRes;
          } return scoreRes;
        } else {
          if (SortOrder.Asc.equals(sortOrder)) {
            if (dateRes == 0) {
              return -scoreRes;
            } return dateRes;
          } else {
            if (dateRes == 0) {
              return -scoreRes;
            } return -dateRes;
          }
        }
    }
}
